﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace DutyWeb.UserControls
{
    public partial class PaginationBar : BaseUserControl
    {
        #region Constants and Fields

        private const string CurrentPageID = "lblCurrentPage";
        private const string PageNumberID = "lbtnPageNumber";
        private const int StartIndex = 1;

        private int autoTrackSection = 1;

        private string btnCss;
        private string dlCss;
        private string lblTotalCss;

        private List<int> pageNumbers;
        private List<int> sectionPageNumbers;

        #endregion

        #region Public Events

        public event EventHandler PageIndexChanged;

        #endregion

        #region Public Properties

        /// <summary>
        /// The total count
        /// </summary>
        public int AllCount
        {
            get
            {
                if (ViewState["AllCount"] == null)
                {
                    return 0;
                }

                return (int)ViewState["AllCount"];
            }

            set
            {
                ViewState["AllCount"] = value;
            }
        }

        /// <summary>
        /// The count of items every page
        /// </summary>
        public int PageSize
        {
            get
            {
                if (ViewState["PageSize"] == null)
                {
                    return 0;
                }

                return (int)ViewState["PageSize"];
            }

            set
            {
                ViewState["PageSize"] = value;
            }
        }

        /// <summary>
        /// Page index
        /// </summary>
        public int PageIndex
        {
            get
            {
                if (ViewState["PageIndex"] == null)
                {
                    return 0;
                }

                return (int)ViewState["PageIndex"];
            }

            set
            {
                ViewState["PageIndex"] = value;
            }
        }

        /// <summary>
        /// The flag of auto-binding
        /// </summary>
        public bool AutoBind
        {
            get
            {
                if (ViewState["AutoBind"] == null)
                {
                    return true;
                }

                return (bool)ViewState["AutoBind"];
            }

            set
            {
                ViewState["AutoBind"] = value;
            }
        }

        /// <summary>
        /// The selected page number style
        /// </summary>
        public string CurrentPageCssClass
        {
            get
            {
                if (ViewState["CurrentPageCSSClass"] == null)
                {
                    return string.Empty;
                }

                return (string)ViewState["CurrentPageCSSClass"];
            }

            set
            {
                ViewState["CurrentPageCSSClass"] = value;
            }
        }

        /// <summary>
        /// The datalist style
        /// </summary>
        public string CtrCssClass
        {
            get
            {
                return this.dlCss;
            }

            set
            {
                this.dlCss = value;
            }
        }

        /// <summary>
        /// the button style
        /// </summary>
        public string BtnCssClass
        {
            get
            {
                return this.btnCss;
            }

            set
            {
                this.btnCss = value;
            }
        }

        /// <summary>
        /// the totallabel style
        /// </summary>
        public string TotalLabelCssClass
        {
            get
            {
                return this.lblTotalCss;
            }

            set
            {
                this.lblTotalCss = value;
            }
        }

        /// <summary>
        /// The flag of section pattern
        /// </summary>
        public bool IsSectionPattern
        {
            get
            {
                if (ViewState["IsSectionPattern"] == null)
                {
                    return false;
                }

                return (bool)ViewState["IsSectionPattern"];
            }

            set
            {
                ViewState["IsSectionPattern"] = value;
            }
        }

        /// <summary>
        /// The size of section
        /// </summary>
        public int SectionSize
        {
            get
            {
                if (ViewState["SectionSize"] == null)
                {
                    return 10;
                }

                return (int)ViewState["SectionSize"];
            }

            set
            {
                ViewState["SectionSize"] = value;
            }
        }

        /// <summary>
        /// The start index of section
        /// </summary>
        public int SectionStartIndex
        {
            get
            {
                if (ViewState["SectionStartIndex"] == null)
                {
                    return StartIndex;
                }

                return (int)ViewState["SectionStartIndex"];
            }

            set
            {
                ViewState["SectionStartIndex"] = value;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Override this.DataBind function
        /// </summary>
        public override void DataBind()
        {
            this.CreatePageNumber();

            if (!this.IsSectionPattern)
            {
                this.dlPagination.DataSource = this.pageNumbers;
                this.dlPagination.DataBind();
            }
            else
            {
                if (this.autoTrackSection == 1)
                {
                    this.TrackSectionScope();
                }

                this.CreateSectionPageNumber();
                this.dlPagination.DataSource = this.sectionPageNumbers;
                this.dlPagination.DataBind();
                this.SetButtonStatus();
                this.SetTotalInfo();
            }
        }

        /// <summary>
        /// Reset section index
        /// </summary>
        public void ResetSectionStartIndex()
        {
            this.SectionStartIndex = StartIndex;
        }

        public void TrackSectionScope()
        {
            int res = this.IsInSectionScope(this.PageIndex);
            if (res > 0)
            {
                this.LoopRightMove();
            }
            else if (res < 0)
            {
                this.LoopLeftMove();
            }
        }
        #endregion

        #region Event Handlers

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                //this.btnBack.CssClass = this.BtnCssClass;
                //this.btnNext.CssClass = this.BtnCssClass;
                this.lbtnBack.CssClass = this.BtnCssClass;
                this.lbtnMore.CssClass = this.BtnCssClass; ;
                this.dlPagination.CssClass = this.dlCss;
                this.lblTotal.CssClass = this.lblTotalCss;
            }
        }

        protected void dlPagination_ItemDataBound(object sender, DataListItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
            {
                int index = (int)e.Item.DataItem;
                if (index == this.PageIndex)
                {
                    Label lbl = e.Item.FindControl(CurrentPageID) as Label;
                    lbl.Text = index.ToString();
                    lbl.Visible = true;
                }
                else
                {
                    LinkButton lbtn = e.Item.FindControl(PageNumberID) as LinkButton;
                    lbtn.Text = index.ToString();
                }
            }
        }

        protected void lbtnPageNumber_Click(object sender, EventArgs e)
        {
            LinkButton lbtn = sender as LinkButton;
            int index = Convert.ToInt32(lbtn.Text);
            this.PageIndex = index;
            if (this.AutoBind)
            {
                this.DataBind();
            }

            if (this.PageIndexChanged != null)
            {
                this.PageIndexChanged(this, null);
            }
        }



        #endregion

        #region Private Methods

        private int CalculateAllNum()
        {
            if (this.AllCount <= 0 || this.PageSize <= 0)
            {
                return 0;
            }

            if (this.AllCount <= this.PageSize)
            {
                return 1;
            }

            int leftCount = this.AllCount % this.PageSize;
            int count = this.AllCount / this.PageSize;
            if (leftCount != 0)
            {
                count = count + 1;
            }

            return count;
        }

        private void CreatePageNumber()
        {
            this.pageNumbers = new List<int>();

            int num = this.CalculateAllNum();
            if (num <= 0)
            {
                return;
            }

            for (int i = 0; i < num; i++)
            {
                this.pageNumbers.Add(i + 1);
            }
        }

        private void CreateSectionPageNumber()
        {
            this.sectionPageNumbers = new List<int>();
            int allCount = this.pageNumbers.Count;
            if (allCount <= this.SectionSize)
            {
                this.sectionPageNumbers = this.pageNumbers;
                this.SectionStartIndex = StartIndex;
                return;
            }

            for (int i = this.SectionStartIndex - 1; i < this.SectionStartIndex + this.SectionSize - 1 && i < allCount; i++)
            {
                this.sectionPageNumbers.Add(this.pageNumbers[i]);
            }
        }

        private void SetButtonStatus()
        {
            if (!this.IsSectionPattern)
            {
                //this.btnBack.Visible = false;
                //this.btnNext.Visible = false;
                this.lbtnBack.Visible = false;
                this.lbtnMore.Visible = false;
            }
            else
            {
                //this.btnBack.Visible = true;
                //this.btnNext.Visible = true;
                this.lbtnBack.Visible = true;
                this.lbtnMore.Visible = true;
                int allNum = this.CalculateAllNum();
                if (this.SectionSize >= allNum)
                {
                    //this.btnBack.Visible = false;
                    //this.btnNext.Visible = false;
                    this.lbtnBack.Visible = false;
                    this.lbtnMore.Visible = false;
                    return;
                }

                if (this.SectionStartIndex == 1)
                {
                    //this.btnBack.Visible = false;
                    this.lbtnBack.Visible = false;
                    return;
                }

                if (this.SectionStartIndex + this.SectionSize - 1 >= allNum)
                {
                    //this.btnNext.Visible = false;
         
                    this.lbtnMore.Visible = false;
                    return;
                }
            }
        }

        private void SetTotalInfo()
        {
            if (this.pageNumbers.Count != 0)
            {
                this.lblTotal.Text = string.Format("{0} / {1}", this.PageIndex, this.pageNumbers.Count);
            }
            else
            {
                this.lblTotal.Text = string.Empty;
            }
        }

        private void LeftMoveSection()
        {
            if (this.SectionStartIndex <= 0)
            {
                return;
            }

            int left = this.SectionStartIndex - this.SectionSize;
            if (left >= 0)
            {
                this.SectionStartIndex = left;
            }
            else
            {
                this.SectionStartIndex = StartIndex;
            }
        }

        private void RightMoveSection()
        {
            int allNum = this.CalculateAllNum();
            int right = this.SectionStartIndex + this.SectionSize;

            if (right <= allNum)
            {
                this.SectionStartIndex = right;
            }
        }

        /// <summary>
        /// Judge whether the page index is in section scope or not
        /// </summary>
        /// <param name="pageIndex">page index</param>
        /// <returns>0: page index in section scope; 1: page index is greater than the section; -1: page index is less than the section;</returns>
        private int IsInSectionScope(int pageIndex)
        {
            int start = this.SectionStartIndex - 1;
            int end = this.SectionStartIndex + this.SectionSize - 1;
            if (pageIndex >= start && pageIndex <= end)
            {
                return 0;
            }
            else
            {
                if (pageIndex < start)
                {
                    return -1;
                }
                else
                {
                    return 1;
                }
            }
        }

        private void LoopLeftMove()
        {
            int res = -1;
            do
            {
                this.LeftMoveSection();
                res = this.IsInSectionScope(this.PageIndex);
            }
            while (res < 0 && this.SectionStartIndex > 1);
        }

        private void LoopRightMove()
        {
            int all = this.CalculateAllNum();
            int res = 1;
            do
            {
                this.RightMoveSection();
                res = this.IsInSectionScope(this.PageIndex);
            }
            while (res > 0 && this.SectionStartIndex < all);
        }

        #endregion

        protected void lbtnBack_Click(object sender, EventArgs e)
        {
            this.autoTrackSection = 0;
            this.LeftMoveSection();
            this.DataBind();
        }

        protected void lbtnMore_Click(object sender, EventArgs e)
        {
            this.autoTrackSection = 0;
            this.RightMoveSection();
            this.DataBind();
        }
    }
}